
#include "include.h"


volatile INPWM_DutyCycleENUM INPWM_DutyCycle;
volatile u32 u32TimBaseCnt = 0u;
INPWM_CheckType INPWM_Check={0};
PWM_SpeedControlFlagType PWM_SpeedControlFlag;
volatile INPWM_CaptureFlagENUM INPWM_CaptureFlag;
volatile u32 u32INPWM_CycleValue = 0u;
volatile u32 u32INPWM_HighLevelValue = 0u;
volatile u8 Uart_TXFlag=0u;
volatile u16 u16RepCntVal=0u;



static void Nvic_InPWM(void)
{
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}

static void INPWM_TIM_Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_ICInitTypeDef TIM_ICInitStruct;
	
	INPWM_RCCClockCmd(); 
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;    //72M/4=18M
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = INPWM_TIM_ARR;
	TIM_TimeBaseInitStruct.TIM_Prescaler = INPWM_TIM_PSC;
	
	TIM_TimeBaseInit(INPWM_TIM, &TIM_TimeBaseInitStruct);
	
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStruct.TIM_ICFilter = 0x00;                             //18M/16/8 = 140.625K   1000HZ 1%zhankongbi 10us  
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_PWMIConfig(INPWM_TIM,&TIM_ICInitStruct);
	
	TIM_SelectInputTrigger(INPWM_TIM, TIM_TS_TI1FP1);
	TIM_SelectSlaveMode(INPWM_TIM, TIM_SlaveMode_Reset);
	TIM_SelectMasterSlaveMode(INPWM_TIM, TIM_MasterSlaveMode_Enable);
	
	Nvic_InPWM();
	TIM_ITConfig(INPWM_TIM,TIM_IT_CC1|TIM_IT_Update,ENABLE);
	TIM_ClearITPendingBit(INPWM_TIM,TIM_IT_CC1|TIM_IT_Update);
	
	TIM_ARRPreloadConfig(INPWM_TIM,ENABLE);
	TIM_Cmd(INPWM_TIM,ENABLE);
}


static void Nvic_TIMBASE(void)
{
	NVIC_InitTypeDef NVIC_InitStruct;

	NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStruct);
}


static void TIMBASE_Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	
	TIMBASE_RCCClockCmd(); 
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = TIMBASE_ARR;
	TIM_TimeBaseInitStruct.TIM_Prescaler = TIMBASE_PSC;
	TIM_TimeBaseInit(TIMBASE, &TIM_TimeBaseInitStruct);
	
	Nvic_TIMBASE();

	TIM_ITConfig(TIMBASE,TIM_IT_Update,ENABLE);
	TIM_ClearITPendingBit(TIMBASE,TIM_IT_Update);
	TIM_ARRPreloadConfig(TIMBASE,ENABLE);
	
	
	
	TIM_Cmd(TIMBASE,ENABLE);
	TIM_SelectOutputTrigger(TIMBASE, TIM_TRGOSource_Update);
}

void TIMBASE_IRQHandler(void)
{
	if(TIM_GetITStatus(TIMBASE,TIM_IT_Update)==SET)
	{
		TIM_ClearITPendingBit(TIMBASE,TIM_IT_Update);
		u32TimBaseCnt++;
	}else{;}
}



static void OUTPWM_TIM_Init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	
	OUTPWM_RCCClockCmd(); 
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = OUTPWM_TIM_ARR;
	TIM_TimeBaseInitStruct.TIM_Prescaler = OUTPWM_TIM_PSC;
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(OUTPWM_TIM, &TIM_TimeBaseInitStruct);
	
	TIM_CtrlPWMOutputs(OUTPWM_TIM, ENABLE);
	
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse = 0;
	TIM_OC1Init(OUTPWM_TIM,&TIM_OCInitStruct);
	
	TIM_OC2Init(OUTPWM_TIM,&TIM_OCInitStruct);
	
	TIM_ARRPreloadConfig(OUTPWM_TIM,ENABLE);
	TIM_Cmd(OUTPWM_TIM,ENABLE);
}


void Tim_Config(void)
{
	TIMBASE_Init();
	INPWM_TIM_Init();
	OUTPWM_TIM_Init();
}

void INPWM_TIM_IRQHandler(void)
{
	if(TIM_GetITStatus(INPWM_TIM,TIM_IT_CC1)==SET)
	{
	  u32INPWM_CycleValue = (u32)((INPWM_TIM->CCR1)+1);
	  u32INPWM_HighLevelValue = (u32)((INPWM_TIM->CCR2)+1);
		INPWM_CaptureFlag = Capture_Ok;
		TIM_ClearITPendingBit(INPWM_TIM,TIM_IT_Update);
	}
	if(TIM_GetITStatus(INPWM_TIM,TIM_IT_Update)==SET)
	{
		u16RepCntVal++;
		INPWM_CaptureFlag = Capture_No;
		TIM_ClearITPendingBit(INPWM_TIM,TIM_IT_Update);
	}else{;}
#if (UART_SWITCH == UART_ON)
	Uart_TXFlag=1;
#endif
}

static void INPWM_IoStatus(GPIO_TypeDef * Gpio_Port,u16 Io)
{
	static u16 u16INPWM_IoStatusFlag = 0x5555;
	u8 bRes = 0;
	
	bRes = GPIO_ReadInputDataBit(Gpio_Port,Io);
	
	u16INPWM_IoStatusFlag = (u16)((u16INPWM_IoStatusFlag<<1)|bRes);
	
	if(0x0000 == u16INPWM_IoStatusFlag) 
	{
//		INPWM_DutyCycle = DutyCycle_0;
		INPWM_Check.u32INPWM_FinalDutyCycle = PWMDuty_0;
		INPWM_DutyCycle = DutyCycle_Valid;
	}
	else if(0xFFFF == u16INPWM_IoStatusFlag)
	{
//		INPWM_DutyCycle = DutyCycle_100;
		INPWM_Check.u32INPWM_FinalDutyCycle = PWMDuty_100;
		INPWM_DutyCycle = DutyCycle_Valid;
		
	}else{;}
}

static Bool INPWM_ConsistencyCheck(u32 Freq,u32 DutyCycle)
{
	Bool bRes = FALSE;
	INPWM_Check.u32INPWM_CurFreq = Freq;
	INPWM_Check.u32INPWM_CurDutyCycle = DutyCycle;
	if(INPWM_Check.u32INPWM_CurFreq > INPWM_Check.u32INPWM_LastFreq)
	{
		INPWM_Check.u32INPWM_AddFreq = INPWM_Check.u32INPWM_CurFreq - INPWM_Check.u32INPWM_LastFreq;
	}
	else
	{
		INPWM_Check.u32INPWM_AddFreq = INPWM_Check.u32INPWM_LastFreq - INPWM_Check.u32INPWM_CurFreq;
	}
	if(INPWM_Check.u32INPWM_CurDutyCycle > INPWM_Check.u32INPWM_LastDutyCycle)
	{
		INPWM_Check.u32INPWM_AddDutyCycle = INPWM_Check.u32INPWM_CurDutyCycle - INPWM_Check.u32INPWM_LastDutyCycle;
	}
	else
	{
		INPWM_Check.u32INPWM_AddDutyCycle = INPWM_Check.u32INPWM_LastDutyCycle - INPWM_Check.u32INPWM_CurDutyCycle;
	}
	INPWM_Check.u32INPWM_LastFreq = INPWM_Check.u32INPWM_CurFreq;
	INPWM_Check.u32INPWM_LastDutyCycle = INPWM_Check.u32INPWM_CurDutyCycle;
	if((INPWM_Check.u32INPWM_AddFreq <= INPWM_FreqDiffValue)&&(INPWM_Check.u32INPWM_AddDutyCycle <= INPWM_DutyCycleDiffValue))
	{
		if(INPWM_Check.u8CheckCnt<255)
		{
			INPWM_Check.u8CheckCnt++;
		}else{;}
	}
	else
	{
		INPWM_Check.u8CheckCnt=0;
	}
	if(INPWM_Check.u8CheckCnt < INPWM_ConsistencyCheckCnt)
	{
		return bRes;
	}
	else
	{
		bRes = TURE;
		INPWM_Check.u32INPWM_FinalFreq = INPWM_Check.u32INPWM_CurFreq;
		INPWM_Check.u32INPWM_FinalDutyCycle = INPWM_Check.u32INPWM_CurDutyCycle;
	}
	return bRes;
}

static void INPWM_GetPwmStatus(void)
{
	Bool bRes = FALSE;
	u32 u32INPWM_Freq =0u;
  u32 u32INPWM_DutyCycle =0u;
	switch(INPWM_CaptureFlag)
	{
		case Capture_Ok:
			for(u16 i=0;(i<u16RepCntVal);i++)
			{
				u32INPWM_CycleValue += 65536;
			}
			u16RepCntVal = 0;
			if((u32INPWM_CycleValue<=INPWM_TIM_MinValidFreqCnt)&&(u32INPWM_CycleValue>=INPWM_TIM_MaxValidFreqCnt))
			{
				u32INPWM_Freq = (u32)(600000000UL/u32INPWM_CycleValue);
				u32INPWM_DutyCycle = (u32)(u32INPWM_HighLevelValue*10000UL/u32INPWM_CycleValue);
				bRes = INPWM_ConsistencyCheck(u32INPWM_Freq,u32INPWM_DutyCycle);
				if(TURE == bRes)
				{
					INPWM_DutyCycle = DutyCycle_Valid;
					
				}
				else
				{
					INPWM_DutyCycle = DutyCycle_InValid;
				}
			}
			else
			{
				u32INPWM_Freq = (u32)(600000000UL/u32INPWM_CycleValue);
				u32INPWM_DutyCycle = (u32)(u32INPWM_HighLevelValue*10000UL/u32INPWM_CycleValue);
				INPWM_DutyCycle = DutyCycle_InValid;
			}
			INPWM_CaptureFlag = Capture_No;
		  break;
		case Capture_No:
			if(u16RepCntVal>100)
			{
				INPWM_IoStatus(INPWM_PORT,INPWM_IO);
			}
		  break;
		case No_StartCapture:
			break;
		default :
			break;
	}
}
	

static u16 PWM_SpeedRegulate(u32 dutycycle)
{
	static u8 MotorStatus = OFF; 
	u16 u16SpeedVal=0u;
	if(dutycycle>=ONPWMDuty)
	{
		MotorStatus = ON;
	}
	else if(dutycycle<=OFFPWMDuty)
  {
		MotorStatus = OFF;
	}
  else{;}
	if(ON == MotorStatus)
	{
		if(dutycycle<=MINPWMDuty)
		{
			u16SpeedVal = MOTOR_SPEED_MIN_RPM;
		}
		else if(dutycycle>=MAXPWMDuty)
		{
			u16SpeedVal = MOTOR_SPEED_MAX_RPM;
		}
		else
		{
			u16SpeedVal = MOTOR_SPEED_MIN_RPM + SPEED_K * ((dutycycle - MINPWMDuty)/100);   
		}
	}
	else
	{
		u16SpeedVal = 0;
	}
	return u16SpeedVal;
}

static void OUTPWM_ChangeOutPwm(void)
{
	switch(PWM_SpeedControlFlag.PWM_SpeedFlag)
	{
		case Speed_Reach:
			PWM_SpeedControlFlag.u32TargetVal = PWM_SpeedRegulate(INPWM_Check.u32INPWM_FinalDutyCycle);
		  if(PWM_SpeedControlFlag.u32CurVal != PWM_SpeedControlFlag.u32TargetVal)
			{
				PWM_SpeedControlFlag.PWM_SpeedFlag = Speed_NotReach;
			}else{;}
			break;
		case Speed_NotReach:
			if(PWM_SpeedControlFlag.u32CurVal != PWM_SpeedControlFlag.u32TargetVal)
			{
				if(PWM_SpeedControlFlag.u32TargetVal > PWM_SpeedControlFlag.u32CurVal)
				{
					PWM_SpeedControlFlag.PWM_SpeedChange = Rising;
				}
				else
				{
					PWM_SpeedControlFlag.PWM_SpeedChange = Falling;
				}
				PWM_SpeedControlFlag.u8SpeedTimeCnt++;
				if(PWM_SpeedControlFlag.u8SpeedTimeCnt>=SlowStartTime)
				{
					PWM_SpeedControlFlag.u8SpeedTimeCnt = 0;
					if(Rising == PWM_SpeedControlFlag.PWM_SpeedChange)
					{
						PWM_SpeedControlFlag.u32CurVal += OUTPWM_TIM_SingleVal;
						TIM_SetCompare1(OUTPWM_TIM,PWM_SpeedControlFlag.u32CurVal);
						TIM_SetCompare2(OUTPWM_TIM,PWM_SpeedControlFlag.u32CurVal);
						
					}
					else if(Falling==PWM_SpeedControlFlag.PWM_SpeedChange)
					{
						PWM_SpeedControlFlag.u32CurVal -= OUTPWM_TIM_SingleVal;
						TIM_SetCompare1(OUTPWM_TIM,PWM_SpeedControlFlag.u32CurVal);
						TIM_SetCompare2(OUTPWM_TIM,PWM_SpeedControlFlag.u32CurVal);
					}
					else
					{
						;
					}
				}else{;}
		  }
			else
			{
				PWM_SpeedControlFlag.PWM_SpeedChange = UnChange;
				PWM_SpeedControlFlag.PWM_SpeedFlag = Speed_Reach;
			}
			break;
		case Speed_Init:
			PWM_SpeedControlFlag.u32TargetVal = PWM_SpeedRegulate(INPWM_Check.u32INPWM_FinalDutyCycle);
		  if(PWM_SpeedControlFlag.u32CurVal != PWM_SpeedControlFlag.u32TargetVal)
			{
				PWM_SpeedControlFlag.PWM_SpeedFlag = Speed_NotReach;
			}else{;}
			break;
		case No_Start:
			break;
		default :
			break;
	}
}

void PWM_MotorControl(void)
{
	INPWM_GetPwmStatus();
	switch(INPWM_DutyCycle)
	{
		case DutyCycle_Valid:
			if(No_Start == PWM_SpeedControlFlag.PWM_SpeedFlag)
			{
				PWM_SpeedControlFlag.PWM_SpeedFlag = Speed_Init;
			}
			break;
		case DutyCycle_InValid:
			break;
		default :
			break;
	}
	OUTPWM_ChangeOutPwm();
}








